#include <fstream>
#include "json.hpp"

using namespace std;

struct BeaconInfo
{
	string beaconAddress;
	vector<float> distances;
};
vector<BeaconInfo> beacons;

int findBeaconIdx(string beaconAddress);
void addReceivedInfo(int idx, int k, nlohmann::json node);

int main(int argc, char **argv)
{
	string src_fn = argc > 1 ? argv[1] : "../ak-1.json";
	string out_fn = argc > 2 ? argv[2] : "out.txt";

	// beacon info
	

	// parse line by line
	int count = 0;
	ifstream ifs(src_fn);
	string line;

	printf("parse json ");
	while (getline(ifs, line)) {
		printf(".");
		//cout << line << endl;

		try {
			auto nodes = nlohmann::json::parse(line.c_str());

			int n_beacons = nodes["beacons"].size();
			for (int i = 0; i < n_beacons; ++i) {
				string addr = nodes["beacons"][i]["beaconAddress"];
				int idx = findBeaconIdx(addr);
				addReceivedInfo(idx, count, nodes["beacons"][i]);
			}

			count++;
		} catch (...) {}
	}
	printf("[%d lines]\n", count);

	// print distances
	ofstream ofs(out_fn);
	for (int i = 0; i < beacons.size(); ++i)
		ofs << beacons[i].beaconAddress << " ";
	ofs << endl;

	vector<float> moving_ave(beacons.size(), 0);
	for (int k = 0; k < count; ++k) {
		for (int i = 0; i < beacons.size(); ++i) {
			if (moving_ave[i] == 0) {
				moving_ave[i] = beacons[i].distances[k];
			} else if (beacons[i].distances[k] != 0) {
				moving_ave[i] = 0.95 * moving_ave[i] + 0.05 * beacons[i].distances[k];
			}

#if 0
			printf("%.4f ", moving_ave[i]);
			ofs << moving_ave[i] << " ";
#else
			printf("%.4f ", beacons[i].distances[k]);
			ofs << beacons[i].distances[k] << " ";
#endif
		}
		printf("\n");
		ofs << endl;
	}

	return 0;
}

int findBeaconIdx(string beaconAddress)
{
	for (int i = 0; i < beacons.size(); ++i)
		if (beacons[i].beaconAddress == beaconAddress)
			return i;

	beacons.push_back(BeaconInfo());
	beacons.back().beaconAddress = beaconAddress;
	return beacons.size() - 1;
}

void addReceivedInfo(int idx, int count, nlohmann::json node)
{
	BeaconInfo &beacon = beacons[idx];
	if (beacon.distances.size() < count) {
		for (int i = beacon.distances.size(); i < count; ++i)
			beacon.distances.push_back(0);
	}

	beacon.distances.push_back(node["distance"]);
}
